/**
 * Author(s): xuming.Wong <xuming.Wong@gmail.com>
 */
#include "Application.h"

#include "GlobalVariables.h"
#include "InputSystem.h"
#include "LoginScene.h"
#include "CharacterSelectScene.h"
#include "ServerChangeScene.h"

namespace PQClient
{
	Application::Application() : _inited(false),_hInst(0),
		_activeScene(Scene_Type_Unkown),_lastScene(Scene_Type_Unkown)
	{
		for(int i=0;i<Scene_Type_Count;++i){
			_scenes[i]=0;
		}
		//We need to accept login event
		this->acceptEvent(Event::Event_Login_Success);
		this->acceptEvent(Event::Event_Server_Change);
	}

	Application::~Application()
	{
	}


	void Application::init(HINSTANCE hInst)
	{
		if(_inited){
			assert("Can only set once!");
		}else{
			_hInst=hInst;
		}

		//init ogre
		_root=new Ogre::Root();
		_root->showConfigDialog();
		_win=_root->initialise(true,"PQ3D");
		defineResource();

		InputSystem::getSingleton().init(_win);


		srand((unsigned)_timer.getMilliseconds());
		
		_scenes[Scene_Type_Login]=new LoginScene(_win);
		_scenes[Scene_Type_CharacterSelect]=new CharacterSelectScene(_win);
		_scenes[Scene_Type_ServerChange]=new ServerChangeScene(_win);
		
		_lastTime=_timer.getMilliseconds();
		
	}

	//The resource that the whole system need
	void Application::defineResource()
	{
		Ogre::ConfigFile cf;
		cf.load("resources.cfg");
		Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();

		Ogre::String secName, typeName, archName;
		while(seci.hasMoreElements()){
			secName = seci.peekNextKey();
			Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
			Ogre::ConfigFile::SettingsMultiMap::iterator i;
			for(i = settings->begin(); i != settings->end(); ++i){
				typeName = i->first;
				archName = i->second;
				Ogre::ResourceGroupManager::getSingleton().addResourceLocation(archName, typeName, secName);
			}
		}

		Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
	}

	void Application::run()
	{
		MSG msg;
		ZeroMemory(&msg, sizeof(MSG));

		while (true){
			while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { 
				if (msg.message == WM_QUIT){
					return;
				}
				TranslateMessage(&msg);
				DispatchMessage(&msg);

				update();
				render();

			}
		
		}

	}

	void Application::update()
	{
		if(_activeScene!=_lastScene){
			if(_scenes[_activeScene]){
				_scenes[_activeScene]->activate();
			}
			
			_lastScene=_activeScene;
		}

		Ogre::Real deltaT=(_timer.getMilliseconds()-_lastTime)/1000.0f;
		_lastTime=_timer.getMilliseconds();

		//update active scene
		_scenes[_activeScene]->update(deltaT);

		

	}

	void Application::render()
	{
		Ogre::Root::getSingleton().renderOneFrame();
	}

	void Application::handleEvent(Event* evt)
	{
		if(!evt||evt->isHandled()||!evt->sender()){
			return;
		}

		Object* sender=evt->sender();
		switch(evt->type()){
		case Event::Event_Login_Success:
			setActiveScene(Scene_Type_CharacterSelect);
			break;
		case Event::Event_Server_Change:
			setActiveScene(Scene_Type_ServerChange);
			break;
		default:
			break;
		}
	}

}
